﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using SH_VBoxVM_Service.Classes;
using System.Threading;
using Microsoft.Win32;



//using SH_VBoxLibrary;

namespace SH_VBoxVM_Service
{
    public partial class VBoxService : ServiceBase
    {

        /// <summary>
        /// Warning: WindowsService Name is: "VBoxTrinketService"
        /// Changes to the name should be reflected in Wix Projet, 
        /// ServiceBase inhereted designer Class, UtilInstaller Class, and TrayClass Class.
        /// </summary>


        IVBoxGreatManager VBGM = null;

        public VBoxService()
        {
            InitializeComponent();


            this.CanHandleSessionChangeEvent = true;


            //SessionEnd Event.
            //Microsoft.Win32.SystemEvents.SessionEnding += new Microsoft.Win32.SessionEndingEventHandler(SystemEvents_SessionEnding);
            
            //Take this into consideration if last attempt doesnt work
            SystemEvents.EventsThreadShutdown += new EventHandler(eventThread_BeforeShutdown);
        }



        /// <summary>
        /// Runs when the Windows Service is Stopped.
        /// </summary>
        /// <param name="args"></param>
        protected override void OnStart(string[] args)
        {
            //Helps Debug
            //NOTE: remove for deployment.
            //System.Diagnostics.Debugger.Launch();

            //ask for more time.
            this.RequestAdditionalTime(2 * 1000 * 60);


            //Proposed Solution: Have TrayApp initiate at startup and in turn start the service.
            //or have the ServiceState be saved in the ConfigFile.
            ThreadPool.QueueUserWorkItem(new WaitCallback((_) =>
            {

               Thread.Sleep(3 * 1000 * 60);//simulate 3 minutes to let everything set up.


                //reading Config File. FIRST THING TO DO VERY IMPORTANT.
                ConfigIO.readConfig();

                VBGM = new VBoxGreatManager();

                VBGM.startEngine();
            }));
        

        }

        /// <summary>
        /// Runs when the Windows Service is stopped.
        /// </summary>
        protected override void OnStop()
        {
            //tring filename = @"C:\Program Files\Oracle\VirtualBox\vboxmanage.exe";    
            //string stopit = string.Format(@"controlvm {0} poweroff", "WIN2K");
            //Process pr = ApplicationLoader.CreateProcessAsUser(filename, stopit);

            //ask for 1 min of stop time.
            this.RequestAdditionalTime(2 * 1000 * 60); 
            VBGM.stopEngine();

        }

        /// <summary>
        /// Runs when the Windows OS is Shutteddown or Restarted.
        /// </summary>
        protected override void OnShutdown()
        {

            this.RequestAdditionalTime(2 * 1000 * 60); 
            VBGM.stopEngine();

        }



        /// <summary>
        /// Unfortunately this event is not working correctly.
        /// because it doesn't allow enough time for my service to call the process and stop it.
        /// </summary>
        /// <param name="changeDescription"></param>
        protected override void OnSessionChange(SessionChangeDescription changeDescription)
        {
            base.OnSessionChange(changeDescription);

            //ask for 2 min of stop time.
            this.RequestAdditionalTime(2 * 1000 * 60); 

            VBGM.stopEngine();

        }



        /// <summary>
        /// Event is fired by WIN32 when session is about to begin ending, this might help me do what I want. 
        /// 
        /// Hopefully it works.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void SystemEvents_SessionEnding(object sender, Microsoft.Win32.SessionEndingEventArgs e)
        {
            //this is bad practice... always respect users request.
            //e.Cancel = true;



            VBGM.stopEngine();
        }


        void eventThread_BeforeShutdown(object sender, EventArgs e)
        {
     
            VBGM.stopEngine();
        }
    }
}
